#pragma once

// simple allocator and re-allocator for object, which is just for simple thread

#include "dynamicpool.h"
#include "objpool.h"
#include <assert.h>

namespace KCP {
	// declare
#define DYNAMIC_DECLARE(type, InitSize, GrowSize)  \
private:                                           \
	static CDynamicPoolEx<type> g_oDynamicPool;    \
	                                               \
public:                                            \
	static type* FetchObj()  {                     \
	    static bool g_bInit = false;               \
        if (!g_bInit) {                            \
	        bool bRet = g_oDynamicPool.Init((InitSize), (GrowSize)); \
			assert(bRet && "pool init error");     \
			g_bInit = true;                        \
        }                                          \
        return g_oDynamicPool.FetchObj();          \
    }                                              \
	                                               \
	static void ReleaseObj(type *poObj) {          \
	    g_oDynamicPool.ReleaseObj(poObj);          \
	}                                              \

// implement
#define DYNAMIC_IMPLEMENT(type)                    \
	CDynamicPoolEx<type> type::g_oDynamicPool;     \

//
//
//

// declare
#define DYNAMIC_DECLAREEX(type, InitSize, GrowSize)   \
private:                                              \
	static CDynamicPoolEx<type> g_oDynamicPool;       \
	                                                  \
public:                                               \
	template <typename Refer>                         \
	static type* FetchObj(Refer&& ...refer) {         \
	    static bool g_bInit = false;                  \
	    if (!g_bInit) {                               \
	        g_oDynamicPool.Init((InitSize), (GrowSize));\
	        g_bInit = true;                           \
	   }                                              \
	   return g_oDynamicPool.fetch_obj(std::forward<Refer>(refer)...); \
	}                                                 \
	static void ReleaseObj(type *poObj)  {            \
	     g_oDynamicPool.ReleaseObj(poObj);            \
	}                                                 \


// implement
#define DYNAMIC_IMPLEMENTEX(type)                    \
	CDynamicPoolEx<type> type::g_oDynamicPool;       \

//
//
//

//
// == simple object pool ==
// support parameter and non parameter fetch.
//
#define DYNAMIC_SIMPLE_DECLARE(type, init_size, grow_size) \
private:                                                   \
	static SObjPoolSpace::object_pool<type, true> g_oDynamicPool; \
	                                                  \
public:                                               \
	template <typename... Refer>                      \
	static type* fetch_obj(Refer&&... refer) {        \
	    static bool g_bInit = false;                  \
	    if (!g_bInit) {                               \
	        g_oDynamicPool.init((init_size), (grow_size));\
	        g_bInit = true;                           \
	   }                                              \
	   return g_oDynamicPool.fetch_obj(refer...);     \
	}                                                 \
	static void release_obj(type *poObj)  {           \
	     g_oDynamicPool.release_obj(poObj);           \
	}                                                 \


//
// implement
//
#define DYNAMIC_SIMPLE_IMPLEMENT(type)                \
	SObjPoolSpace::object_pool<type, true> type::g_oDynamicPool; \


// global pool object declare.
#define DECLEAR_POOL_OBJ(type, constr)            \
    static SObjPoolSpace::object_pool<type, (constr)> pool_##type; \
    static bool g_init_##type = false;            \
    template <typename ...Args>                   \
	inline type* g_create_##type(Args&&...args) { \
        if (!g_init_##type) {                     \
           pool_##type.init(8, 4);                \
           g_init_##type = true;                  \
        }                                         \
        return pool_##type.fetch_obj(args...);    \
	}                                             \
    inline void g_release_##type(type *p) {       \
        pool_##type.release_obj(p);               \
    }

#define CREATE_POOL_OBJ(type, ...) g_create_##type(##__VA_ARGS__)
#define REALEASE_POOL_OBJ(type, p) g_release_##type(p)
}